package cn.shopthrive.merchants;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.util.Log;

import com.heytap.msp.push.HeytapPushManager;
import com.heytap.msp.push.callback.ICallBackResultService;
import com.vivo.push.PushClient;
import com.vivo.push.PushConfig;
import com.vivo.push.listener.IPushQueryActionListener;
import com.vivo.push.util.VivoPushException;

import java.util.HashMap;
import java.util.Map;

import io.flutter.plugin.common.MethodChannel;

public class MyApplication extends Application {
  private MethodChannel pushChannel;
  private static final String PREFS_NAME = "PushPrefs";
  private static final String KEY_REGID_PREFIX = "push_regId_";
  private static final String KEY_TIMESTAMP_PREFIX = "push_timestamp_";
  private static final long CACHE_VALIDITY = 30L * 24 * 60 * 60 * 1000;

  public void setPushChannel(MethodChannel channel) {
    this.pushChannel = channel;
  }

  @Override
  public void onCreate() {
    super.onCreate();
  }

  void initPush(Context context, String brand, boolean agreed) {
    switch (brand) {
      case "vivo":
        initVivoPush(context, agreed);
        break;
      case "huawei":
      case "honor":
      case "xiaomi":
      case "oppo":
        initOppoPush(context, agreed);
        break;
      default:
        Log.w("MyApplication", "Unsupported push brand: " + brand);
        notifyPushError(context, -6, "Brand " + brand + " is not supported");
    }
  }

  private void initVivoPush(Context context, boolean agreed) {
    try {
      PushConfig config = new PushConfig.Builder()
              .agreePrivacyStatement(agreed)
              .build();
      PushClient.getInstance(context).initialize(config);
      if (agreed) {
        requestVivoPushToken(context, false);
      } else {
        PushClient.getInstance(context).turnOffPush(state -> {
          Log.i("MyApplication", "Vivo Push turned off, state: " + state);
          clearPushCache(context, "vivo");
        });
      }
    } catch (VivoPushException e) {
      Log.e("MyApplication", "VivoPushException: Failed to initialize, error: " + e.getMessage(), e);
      notifyPushError(context, -3, "Vivo initialization failed");
    }
  }

  private void initOppoPush(Context context, boolean agreed) {
    if (!HeytapPushManager.isSupportPush(context)) {
      Log.w("MyApplication", "OPPO Push not supported on this device");
      notifyPushError(context, -5, "OPPO Push not supported");
      return;
    }
    HeytapPushManager.init(context, true);
    if (agreed) {
      String appKey = BuildConfig.OPPO_APP_KEY;
      String appSecret = BuildConfig.OPPO_APP_SECRET;
      HeytapPushManager.register(context, appKey, appSecret, new ICallBackResultService() {
        @Override
        public void onRegister(int responseCode, String registerID, String packageName, String miniProgramPkg) {
          if (responseCode == 0 && registerID != null) {
            Log.i("MyApplication", "OPPO regId: " + registerID);
            SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
            prefs.edit()
                    .putString(KEY_REGID_PREFIX + "oppo", registerID)
                    .putLong(KEY_TIMESTAMP_PREFIX + "oppo", System.currentTimeMillis())
                    .apply();
            notifyPushToken(context, "oppo", registerID, null);
          } else {
            Log.e("MyApplication", "OPPO register failed, code: " + responseCode);
            notifyPushToken(context, "oppo", null, responseCode);
          }
        }

        @Override
        public void onUnRegister(int i, String s, String s1) {

        }

        @Override
        public void onSetPushTime(int i, String s) {

        }

        @Override
        public void onGetPushStatus(int i, int i1) {

        }

        @Override
        public void onGetNotificationStatus(int i, int i1) {

        }

        @Override
        public void onError(int i, String s, String s1, String s2) {

        }
      });
    } else {
      HeytapPushManager.unRegister();
      clearPushCache(context, "oppo");
    }
  }

  void requestPushToken(Context context, String brand, boolean forceRefresh) {
    switch (brand) {
      case "vivo":
        requestVivoPushToken(context, forceRefresh);
        break;
      case "huawei":
      case "honor":
      case "xiaomi":
      case "oppo":
        requestOppoPushToken(context, forceRefresh);
        break;
      default:
        Log.w("MyApplication", "Unsupported push brand: " + brand);
        notifyPushError(context, -6, "Brand " + brand + " is not supported");
    }
  }

  private void requestVivoPushToken(Context context, boolean forceRefresh) {
    PushClient.getInstance(context).turnOnPush(state -> {
      if (state != 0) {
        Log.w("MyApplication", "Failed to turn on Vivo Push, state: " + state);
        if (state == 1012) {
          notifyPushError(context, -4, "Vivo push permission is disabled");
        } else {
          notifyPushError(context, state, "Failed to enable Vivo push");
        }
        return;
      }
      Log.i("MyApplication", "Vivo Push turned on successfully");

      if (!forceRefresh) {
        SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        String cachedRegId = prefs.getString(KEY_REGID_PREFIX + "vivo", null);
        long timestamp = prefs.getLong(KEY_TIMESTAMP_PREFIX + "vivo", 0);
        boolean isCacheValid = cachedRegId != null &&
                (System.currentTimeMillis() - timestamp) < CACHE_VALIDITY;

        if (isCacheValid) {
          Log.i("MyApplication", "Using cached Vivo regId: " + cachedRegId);
          notifyPushToken(context, "vivo", cachedRegId, null);
          return;
        }
      }

      PushClient.getInstance(context).getRegId(new IPushQueryActionListener() {
        @Override
        public void onSuccess(String regId) {
          Log.i("MyApplication", "Vivo regId: " + regId);
          SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
          prefs.edit()
                  .putString(KEY_REGID_PREFIX + "vivo", regId)
                  .putLong(KEY_TIMESTAMP_PREFIX + "vivo", System.currentTimeMillis())
                  .apply();
          notifyPushToken(context, "vivo", regId, null);
        }

        @Override
        public void onFail(Integer errorCode) {
          Log.e("MyApplication", "Failed to get Vivo regId, errorCode: " + errorCode);
          notifyPushToken(context, "vivo", null, errorCode);
        }
      });
    });
  }

  private void requestOppoPushToken(Context context, boolean forceRefresh) {
    if (!HeytapPushManager.isSupportPush(context)) {
      Log.w("MyApplication", "OPPO Push not supported");
      notifyPushError(context, -5, "OPPO Push not supported");
      return;
    }
    if (!forceRefresh) {
      SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
      String cachedRegId = prefs.getString(KEY_REGID_PREFIX + "oppo", null);
      long timestamp = prefs.getLong(KEY_TIMESTAMP_PREFIX + "oppo", 0);
      boolean isCacheValid = cachedRegId != null &&
              (System.currentTimeMillis() - timestamp) < CACHE_VALIDITY;

      if (isCacheValid) {
        Log.i("MyApplication", "Using cached OPPO regId: " + cachedRegId);
        notifyPushToken(context, "oppo", cachedRegId, null);
        return;
      }
    }
    HeytapPushManager.getRegister();
  }

  private void notifyPushToken(Context context, String brand, String token, Integer errorCode) {
    if (pushChannel == null) {
      Log.w("MyApplication", "Push channel is null, cannot notify Flutter for " + brand);
      return;
    }
    Map<String, Object> params = new HashMap<>();
    params.put("brand", brand);
    if (token != null) {
      params.put("token", token);
    }
    if (errorCode != null) {
      params.put("errorCode", errorCode);
    }
    invokeChannelMethod(context, "onPushToken", params);
  }

  public void notifyPushMessage(Context context, Map<String, Object> data) {
    if (pushChannel == null) {
      Log.w("MyApplication", "Push channel is null, cannot notify Flutter for message");
      return;
    }
    invokeChannelMethod(context, "onMessage", data);
  }

  private void notifyPushError(Context context, int errorCode, String message) {
    Log.w("MyApplication", "Push error: " + message + ", code: " + errorCode);
    notifyPushToken(context, getErrorBrand(context), null, errorCode);
  }

  private String getErrorBrand(Context context) {
    return "oppo";
  }

  private void clearPushCache(Context context, String brand) {
    SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
    prefs.edit()
            .remove(KEY_REGID_PREFIX + brand)
            .remove(KEY_TIMESTAMP_PREFIX + brand)
            .apply();
    Log.i("MyApplication", "Cleared push cache for " + brand);
  }

  private void invokeChannelMethod(Context context, String method, Object params) {
    if (context instanceof Activity) {
      ((Activity) context).runOnUiThread(() -> {
        try {
          pushChannel.invokeMethod(method, params);
        } catch (Exception e) {
          Log.e("MyApplication", "Failed to invoke " + method + ": " + e.getMessage(), e);
        }
      });
    } else {
      Log.w("MyApplication", "Context is not an Activity, using direct invoke");
      try {
        pushChannel.invokeMethod(method, params);
      } catch (Exception e) {
        Log.e("MyApplication", "Failed to invoke " + method + ": " + e.getMessage(), e);
      }
    }
  }

  public void openUrl(Context context, String url) {
    try {
      Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context.startActivity(intent);
      Log.i("MyApplication", "Opening URL: " + url);
    } catch (Exception e) {
      Log.e("MyApplication", "Failed to open URL: " + url + ", error: " + e.getMessage(), e);
      notifyPushError(context, -8, "Failed to open URL");
    }
  }
}